//
// Created by 23602 on 2024-07-07.
//

#include "asynctask.hpp"

using namespace std;
void reset(Buffer buff, uint32_t size) {
    buff.clear();
    buff.reserve(size);
}
AsyncTask::AsyncTask(std::function<void(const Buffer&)> onBufferFull, uint32_t maxBuffSize,
                     uint8_t timeout): onBufferFull_(onBufferFull), maxBufferSize(maxBuffSize),
                     timeout_(timeout)
                     {
                         curbuffer_ = std::make_unique<Buffer>();
                         nextBuffer_ = std::make_unique<Buffer>();

    curbuffer_->reserve(maxBufferSize);
    nextBuffer_->reserve(maxBufferSize);
    buffer_.reserve(16);
    taskThread_ = std::thread(&AsyncTask::threadFunc, this);
};
void AsyncTask::append(const Byte* buff, uint32_t size) {
    lock_guard<mutex> lock(mtx_);
    if (!curbuffer_) {
        return;
    }
    if ( !isFull(curbuffer_.get(), size) ) {
        curbuffer_->insert(curbuffer_->end(), buff, buff + size);
        cv_.notify_one();
        return;
    }
    // 满了的情况下，先把当前的buffer_放到buffer_里面
    buffer_.push_back(std::move(curbuffer_));
    if (!isFull(nextBuffer_.get(), size)) {
        curbuffer_ = std::move(nextBuffer_);
    } else {
        curbuffer_.reset(new Buffer(maxBufferSize, 0));
    }
    curbuffer_->insert(curbuffer_->end(), buff, buff + size);
    cv_.notify_one();
}
void AsyncTask::append(const Buffer &buff) {
    this->append(buff.data(), buff.size());
}

void AsyncTask::threadFunc() {
    BufferPtr buffer1 = make_unique<Buffer>();
    BufferPtr buffer2 = make_unique<Buffer>();
    buffer1->reserve(maxBufferSize);
    buffer2->reserve(maxBufferSize);

    // 用于写入到文件中
    BufferPtrVec bufferToWrite;
    // 16 ????
    bufferToWrite.reserve(16);
    while (isRunning_) {
        // 临界区
        {
            unique_lock<mutex> lock(mtx_);
            if (buffer_.empty()) {  // 非常规用法
                cv_.wait_for(lock, chrono::seconds(timeout_));
            }
            buffer_.push_back(std::move(curbuffer_));
            // 装填上备用 buff1
            curbuffer_ = std::move(buffer1);
            bufferToWrite.swap(buffer_);
            // 如果nextBuffer_ 也满了，说明管理的内存已经被curBuffer_ 占有了，next自然也就空了
            if (!nextBuffer_) {
                nextBuffer_ = std::move(buffer2);
            }
        }
        
        // 调用回调函数
        if (!isRunning_ ) {
            break;
        }
        // 也有可能出现写入过快，写入处理不及时
        if (onBufferFull_) {
            for (auto& buffer : bufferToWrite) {
                onBufferFull_(*buffer);
            }
        }

        if (bufferToWrite.size() > 2) {
            bufferToWrite.resize(2);
        }
        // 重新装填buff1 和 buff2
        if (!buffer1 && !bufferToWrite.empty()) {
            buffer1 = std::move(bufferToWrite.back());
            bufferToWrite.pop_back();
            buffer1->clear();
            // ::reset(*buffer1, maxBufferSize);
        }
        if (!buffer2 && !bufferToWrite.empty()) {
            buffer2 = std::move(bufferToWrite.back());
            bufferToWrite.pop_back();
            buffer2->clear();
        }
        bufferToWrite.clear();
    }
}

void AsyncTask::reset() {
    if (curbuffer_) {
        curbuffer_->clear();
        curbuffer_->reserve(maxBufferSize);
    }
    if (nextBuffer_) {
        nextBuffer_->clear();
        nextBuffer_->reserve(maxBufferSize);
    }
    buffer_.clear();
    buffer_.reserve(maxBufferSize);
}
